跳到主要内容

MyBatisPlus 常用的增删改查

基本的 CRUD 操作

通过继承 BaseMapper 就可以获取到各种各样的表单操作,如下所示已经内置了各种各样的方法

image.png

插入操作

例如使用自带的 Insert 方法

@Autowired
private UserMapper userMapper;

@Test
void testInsert() {
User user = new User();
user.setAge(18);
user.setEmail("123@gmail.com");
user.setName("张三");
// 改变的行数
int insert = userMapper.insert(user);
// 会自动把这个自增的 id 属性回填到 User里面
log.info("回填的 id:{}", user.getId());
}

更新操作 UpdateWrapper

最简单的根据 ID 更新

@Test
void updateByIdTest() {
User user = new User(); // 不更新的部分为 null 就行了
user.setId(6L);
user.setAge(20);
int i = userMapper.updateById(user);
log.info("修改了:{} 次", i);
}

根据条件更新,使用 QueryWrapper 的方式

@Test
void updateTest() {
User user = new User(); // 不更新的部分为 null 就行了
user.setId(6L);
user.setAge(21);

QueryWrapper<User> wrapper = new QueryWrapper<>();
wrapper.eq("name", "张三"); // 根据用户名进行更新
// 不等于:ne


int i = userMapper.update(user, wrapper);
log.info("修改了:{} 次", i);
}

根据条件更新,使用 UpdateWrapper 的方式

@Test
void updateTest02() {
UpdateWrapper<User> wrapper = new UpdateWrapper<>();
// 使用这个 UpdateWrapper 可以直接设置需要修改的部分,上面那个 QueryWrapper 好处在于更通用
wrapper.set("age", 22).set("email", "456@gmail.com").eq("name", "张三");

int i = userMapper.update(null, wrapper);
log.info("修改了:{} 次", i);
}

删除操作

@Test
void deleteByIdTest() {
int i = userMapper.deleteById(6L);
log.info("删除了:{} 次", i);
}

根据 columnMap 条件,删除记录

@Test
void deleteByMapTest() {
Map<String, Object> map = new HashMap<>();
map.put("name", "张三");
map.put("age", 22);
int i = userMapper.deleteByMap(map);
log.info("删除了:{} 次", i);
}

使用 QueryWrapper 的方式

@Test
void deleteTest() {
QueryWrapper<User> wrapper = new QueryWrapper<>();
wrapper.eq("name", "张三").eq("age", 22); // 根据用户名查询
int i = userMapper.delete(wrapper);
log.info("删除了:{} 次", i);
}

@Test
void deleteTest02() {
User user = new User(); // 可以直接包装一个 User 对象来当查询条件
user.setName("张三");
user.setAge(21);
QueryWrapper<User> wrapper = new QueryWrapper<>(user);
int i = userMapper.delete(wrapper);
log.info("删除了:{} 次", i);
}

根据 ID 批量删除 deleteBatchIds

@Test
void deleteBatchIdsTest() {
// 删除 id 为 3 到 6 的数据(这里使用了 Arrays 这个工具类的方法)
int i = userMapper.deleteBatchIds(Arrays.asList(3L, 6L));
log.info("删除了:{} 次", i);
}

查询操作

查询数据列表

@Test
void selectTest() {
List<User> userList = userMapper.selectList(null);
}

根据 ID 查询

@Test
void selectByTdTest() {
User user = userMapper.selectById(6L);
}

查询一条数据

@Test
void selectOneTest() {
QueryWrapper<User> wrapper = new QueryWrapper<>();
wrapper.eq("name", "张三"); // 根据用户名查询
User user = userMapper.selectOne(wrapper); // 如果结果不唯一会报错
}

查询数据的条数

@Test
void selectCountTest() {
QueryWrapper<User> wrapper = new QueryWrapper<>();
wrapper.gt("age", 20); // 大于 20
Integer count = userMapper.selectCount(wrapper);
}

使用 lambda 的方式:

// 这里直接贴业务代码
@Override
public IPage<TbTopic> getTopicByTag(int currentPage, int pageSize, String tag) {
Page<TbTopic> page = new Page<>(currentPage, pageSize);
IPage<TbTopic> topicIPage = baseMapper.selectPage(page,
Wrappers.<TbTopic>query().lambda().eq(TbTopic::getTag, tag));

List<TbTopic> newData = topicIPage.getRecords().stream()
.peek(x -> x.setContent(x.getContent().substring(0, 100) + "...")).collect(Collectors.toList());

topicIPage.setRecords(newData);
return topicIPage;
}

分页查询

参考资料 内置插件(since 3.4.0(暂未发布正式版))

需要先配置(注意:官方已经更新分页插件了,所以不是之前那种配置方式)

@Configuration
@MapperScan("com.alsritter.studymybatisplus.mapper") // 可以把 Application 的那个扫描器放到这个配置类上来
public class MyBatisPlusConfig {
/**
* 新的分页插件,一缓和二缓遵循 mybatis 的规则,
* 需要设置 MybatisConfiguration#useDeprecatedExecutor = false
* 避免缓存出现问题(该属性会在旧插件移除后一同移除)
*/
@Bean
public MybatisPlusInterceptor mybatisPlusInterceptor() {
MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
// 分页插件
interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL));
return interceptor;
}
}

然后就能正常分页了

@Test
void selectPageTest() {
Page<User> page = new Page<>(1, 2); // 查询第一页的,一页大小为 2
QueryWrapper<User> wrapper = new QueryWrapper<>();
wrapper.likeLeft("email", "@gmail").or().gt("age", 15);

IPage<User> iPage = userMapper.selectPage(page, wrapper);
log.info("数据总条数: {}", iPage.getTotal());
log.info("数据总页数: {}", iPage.getPages());
log.info("当前页数: {}", iPage.getCurrent());

List<User> results = iPage.getRecords();
for (User user : results) {
log.info(user.toString());
}
}

条件构造器

参考资料 官方文档 条件构造器

下面只介绍几个特殊点的

allEq 比对

作用就像字面意思一样比对全部 Map 里的字段,但是如果特意设置某个字段为 null 则会拿这个字段的 null 当成比较参数

@Test
void selectTest() {
Map<String, Object> map = new HashMap<>();
map.put("name", "张三");
map.put("age", 22);
map.put("email", null);

QueryWrapper<User> wrapper = new QueryWrapper<>();
wrapper.allEq(map);
// 如果设置为 wrapper.allEq(map, false); 则不会比较上面那个 null 字段
List<User> userList = userMapper.selectList(wrapper);
}

比对 Map 里的内容,并对这个 Map 进行过滤

@Test
void selectTest() {
Map<String, Object> map = new HashMap<>();
map.put("name", "张三");
map.put("age", 22);
map.put("id", 2L);

QueryWrapper<User> wrapper = new QueryWrapper<>();
// 可以对这个 Map 进行一次回调函数(filter)进行筛选需要比对的内容
// 例如这里就只比对 age 和 id 两个字段
wrapper.allEq((k, v) -> (k.equals("age") || k.equals("id")), map);
List<User> userList = userMapper.selectList(wrapper);
}

模糊查询

likeLIKE '%值%'

// 下面的同理
QueryWrapper<User> wrapper = new QueryWrapper<>();
wrapper.like("name", "王");

notLikeNOT LIKE '%值%' likeLifLIKE '%值' lickRightLIKE '值%'

排序操作

// 排序:ORDER BY 字段, ...
// orderBy(true, true, "id", "name")--->order by id ASC,name ASC
orderBy(boolean condition, boolean isAsc, R... columns)

// 排序:ORDER BY 字段, ... DESC
// 例: orderByDesc("id", "name")--->order by id DESC,name DESC
orderByDesc(R... columns)
orderByDesc(boolean condition, R... columns)

// 排序:ORDER BY 字段, ... ASC
// 例: orderByAsc("id", "name")--->order by id ASC,name ASC
orderByAsc(R... columns)
orderByAsc(boolean condition, R... columns)

select

当不需要所有返回值,只需要部分时可以使用这个 select 关键字

select(String... sqlSelect)
select(Predicate<TableFieldInfo> predicate)
select(Class<T> entityClass, Predicate<TableFieldInfo> predicate)

例如:

QueryWrapper<User> wrapper = new QueryWrapper<>();
wrapper.like("name", "王").select("age","name");

多表查询

TODO: 就是 Mybatis 的那种多表查询,目前没有看到啥好办法,以后学到了再更新...

查询用户当前拥有的权限示例:

/**
* 权限表(tb_permission)数据Mapper
*
* @author alsritter
* @since 2021-06-02 00:37:39
* @description auto generator
*/
@Mapper
public interface TbPermissionMapper extends BaseMapper<TbPermission> {
/**
* 根据用户 id 查询用户权限
* @param userId 用户 ID
* @return 当前用户的权限
*/
@Select("SELECT *\n" +
"FROM tb_permission\n" +
"WHERE id IN (\n" +
" SELECT permission_id\n" +
" FROM tb_role_permission\n" +
" WHERE role_id IN (\n" +
" SELECT role_id\n" +
" FROM tb_user_role\n" +
" WHERE user_id = #{userId}\n" +
" )\n" +
");")
List<TbPermission> findPermissionsByUserId(String userId);
}
/**
* 用户表(tb_user)数据 Mapper
*
* @author alsritter
* @description 查询角色
* @since 2021-06-02 00:37:39
*/
@Mapper
public interface TbUserMapper extends BaseMapper<TbUser> {

@Select("SELECT * FROM `tb_user` WHERE username = #{username} limit 1")
@Results({
@Result(id = true, property = "id", column = "id"),
// `column = "id"` 是指将 user 表中的用户主键 id 作为 `findPermissionsByUserId` 的查询参数
@Result(property = "permissions", column = "id", javaType = List.class,
many = @Many(select = "com.alsritter.mapuaa.mapper.TbPermissionMapper.findPermissionsByUserId"))
})
TbUser getUserByUsername(String username);
}